<?php
declare (strict_types = 1);

namespace app\common\controller;

use think\App;
use think\facade\View;

/**
 * 控制器基础类
 */
abstract class Controller
{
    /**
     * Request实例
     * @var \think\Request
     */
    protected $request;

    /**
     * 应用实例
     * @var \think\App
     */
    protected $app;

    /**
     * 控制器中间件
     * @var array
     */
    protected $middleware = [];

    /**
     * 传递到页面的变量数据
     * @var array
     */
    protected $assignData = [];

    /**
     * 传递到js中的数据
     * @var array
     */
    protected $assignJsData = [];

    /**
     * 传递到页面的css、js文件路径
     * @var array
     */
    protected $assignStatic = [
        'css' => [],
        'js' => [],
        'deferJs' => []
    ];

    /**
     * 传递网页标题、关键词、描述
     * @var array
     */
    protected $assignMeta = [
        'title' => [],
        'keywords' => [],
        'description' => []
    ];

    protected $params = [];

    /**
     * 构造方法
     * @access public
     * @param  App  $app  应用对象
     */
    public function __construct(App $app)
    {
        $this->app     = $app;
        $this->request = $this->app->request;

        // 控制器初始化
        $this->initialize();
    }

    // 初始化
    protected function initialize()
    {

        $this->params = [
            'controller' => $this->request->controller()
        ];

        // url访问到public
        $this->assign('root', $this->request->realRoot());
        $this->assign('absroot', $this->request->realRoot(true));
        $this->assignJsData('root', $this->request->realRoot());
        $this->assignJsData('absroot', $this->request->realRoot(true));
        $this->assignJsData('approot', $this->request->root());

        // url访问到static
        $this->assign('static', $this->request->realRoot() . 'static' . '/');
        $this->assign('absstatic', $this->request->realRoot(true) . 'static' . '/');
        // 判断当前是否是手机请求
        $this->assign('isMobile', $this->request->isMobile());
    }

    /**
     * 传递变量到页面中
     * @param $name 变量名
     * @param $value 值
     */
    protected function assign($name, $value)
    {
        if (is_array($name)) {
            $this->assignData = array_merge($this->assignData, $name);
        } else {
            $this->assignData[$name] = $value;
        }
    }

    /**
     * 传递数据到JS中
     * @param $name
     * @param $value
     */
    protected function assignJsData($name, $value)
    {
        if (is_array($name)) {
            $this->assignJsData = array_merge($this->assignData, $name);
        } else {
            $this->assignJsData[$name] = $value;
        }
    }

    /**
     * 渲染模板
     * @param string $template  模板名
     * @param array $data
     * @return string
     */
    protected function fetch(string $template = '', array $data = [])
    {
        $this->assignData = array_merge($this->assignData, $data);
        // 把CSS、JS、网站标题、关键词、描述传到模板中
        $this->assign('css', $this->assignStatic['css']);
        $this->assign('js', $this->assignStatic['js']);
        $this->assign('deferJs', $this->assignStatic['deferJs']);
        $this->assign('meta', $this->assignMeta);
        $this->assign('globalJsData', json_encode($this->assignJsData));
        return View::fetch($template, $this->assignData);
    }

    /**
     * 添加CSS文件
     * @param string $path
     */
    protected function addCss($path)
    {
        if (is_string($path)) {
            array_push($this->assignStatic['css'], $path);
        } elseif (is_array($path)) {
            $this->assignStatic['css'] = array_merge($this->assignStatic['css'], $path);
        }
    }

    /**
     * 移除CSS文件
     * @param string $path
     */
    protected function removeCss($path)
    {
        $path = is_array($path) ? $path : [$path];
        $this->assignStatic['css'] = array_diff($this->assignStatic['css'], $path);
    }

    /**
     * 添加JS文件
     * @param string $path 文件路径
     * @param bool $defer true添加到body结尾  false head中
     */
    protected function addJs($path, $defer = true)
    {
        $key = $defer ? 'deferJs' : 'js';
        if (is_string($path)) {
            array_push($this->assignStatic[$key], $path);
        } elseif (is_array($path)) {
            $this->assignStatic[$key] = array_merge($this->assignStatic[$key], $path);
        }
    }

    /**
     * 移除JS文件
     * @param string $path
     * @param bool $defer
     */
    protected function removeJs($path, $defer = true)
    {
        $key = $defer ? 'deferJs' : 'js';
        $path = is_array($path) ? $path : [$path];
        $this->assignStatic[$key] = array_diff($this->assignStatic[$key], $path);
    }

    /**
     * 追加一个网页标题
     * @param string $title
     */
    protected function addTitle(string $title)
    {
        array_unshift($this->assignMeta['title'], $title);
    }

    /**
     * 重置网页标题
     * @param $title
     */
    protected function  setTitle($title)
    {
        $this->assignMeta['title'] = is_array($title) ? $title : [$title];
    }

    /**
     * 追加一个关键词
     * @param string $title
     */
    protected function addKeywords(string $title)
    {
        array_unshift($this->assignMeta['keywords'], $title);
    }

    /**
     * 重置关键词
     * @param $title
     */
    protected function  setKeywords($title)
    {
        $this->assignMeta['keywords'] = is_array($title) ? $title : [$title];
    }

    /**
     * 追加网站描述
     * @param string $title
     */
    protected function addDescription(string $title)
    {
        array_unshift($this->assignMeta['description'], $title);
    }

    /**
     * 重置网站描述
     * @param $title
     */
    protected function  setDescription($title)
    {
        $this->assignMeta['description'] = is_array($title) ? $title : [$title];
    }
}
